﻿using System;
using System.Runtime.CompilerServices;

namespace LINQPadLogParser
{
  public sealed class TimeSpanMillisecondsWrapper : IFormattable
  {
    private readonly string _value;
    private TimeSpan? _timeSpan;

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public TimeSpanMillisecondsWrapper(string value)
    {
      _value = value;
    }

    private TimeSpan TimeSpan
    {
      [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return (TimeSpan) (_timeSpan ?? (_timeSpan = TimeSpan.FromMilliseconds(int.Parse(_value)))); }
    }

    public long Ticks
    {
      [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return TimeSpan.Ticks; }
    }

    public int Days
    {
      [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return TimeSpan.Days; }
    }

    public int Hours
    {
      [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return TimeSpan.Hours; }
    }

    public int Milliseconds
    {
      [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return TimeSpan.Milliseconds; }
    }

    public int Minutes
    {
      [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return TimeSpan.Minutes; }
    }

    public int Seconds
    {
      [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return TimeSpan.Seconds; }
    }

    public double TotalDays
    {
      [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return TimeSpan.TotalDays; }
    }

    public double TotalHours
    {
      [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return TimeSpan.TotalHours; }
    }

    public double TotalMilliseconds
    {
      [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return TimeSpan.TotalMilliseconds; }
    }

    public double TotalMinutes
    {
      [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return TimeSpan.TotalMinutes; }
    }

    public double TotalSeconds
    {
      [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return TimeSpan.TotalSeconds; }
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public string ToString(string format, IFormatProvider formatProvider)
    {
      return TimeSpan.ToString(format, formatProvider);
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    private bool Equals(TimeSpanMillisecondsWrapper other)
    {
      return string.Equals(_value, other._value);
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public override bool Equals(object obj)
    {
      if (ReferenceEquals(null, obj)) return false;
      if (ReferenceEquals(this, obj)) return true;
      return obj is TimeSpanMillisecondsWrapper && Equals((TimeSpanMillisecondsWrapper) obj);
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public override int GetHashCode()
    {
      return (_value != null ? _value.GetHashCode() : 0);
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public TimeSpan Add(TimeSpan ts)
    {
      return TimeSpan.Add(ts);
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public int CompareTo(object value)
    {
      return TimeSpan.CompareTo(value);
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public int CompareTo(TimeSpan value)
    {
      return TimeSpan.CompareTo(value);
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public TimeSpan Duration()
    {
      return TimeSpan.Duration();
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public bool Equals(TimeSpan obj)
    {
      return TimeSpan.Equals(obj);
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public TimeSpan Negate()
    {
      return TimeSpan.Negate();
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public TimeSpan Subtract(TimeSpan ts)
    {
      return TimeSpan.Subtract(ts);
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public string ToString(string format)
    {
      return TimeSpan.ToString(format);
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static TimeSpan operator -(TimeSpanMillisecondsWrapper t)
    {
      return -t.TimeSpan;
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static TimeSpan operator -(TimeSpanMillisecondsWrapper t1, TimeSpan t2)
    {
      return t1.TimeSpan.Subtract(t2);
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static TimeSpan operator +(TimeSpanMillisecondsWrapper t)
    {
      return t.TimeSpan;
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static TimeSpan operator +(TimeSpanMillisecondsWrapper t1, TimeSpan t2)
    {
      return t1.TimeSpan.Add(t2);
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static bool operator ==(TimeSpanMillisecondsWrapper t1, TimeSpan t2)
    {
      return t1 != null && t1.TimeSpan == t2;
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static bool operator !=(TimeSpanMillisecondsWrapper t1, TimeSpan t2)
    {
      return t1 != null && t1.TimeSpan != t2;
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static bool operator <(TimeSpanMillisecondsWrapper t1, TimeSpan t2)
    {
      return t1.TimeSpan < t2;
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static bool operator <=(TimeSpanMillisecondsWrapper t1, TimeSpan t2)
    {
      return t1.TimeSpan <= t2;
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static bool operator >(TimeSpanMillisecondsWrapper t1, TimeSpan t2)
    {
      return t1.TimeSpan > t2;
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static bool operator >=(TimeSpanMillisecondsWrapper t1, TimeSpan t2)
    {
      return t1.TimeSpan >= t2;
    }


    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static TimeSpan operator -(TimeSpanMillisecondsWrapper t1, TimeSpanMillisecondsWrapper t2)
    {
      return t1.TimeSpan.Subtract(t2.TimeSpan);
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static TimeSpan operator +(TimeSpanMillisecondsWrapper t1, TimeSpanMillisecondsWrapper t2)
    {
      return t1.TimeSpan.Add(t2.TimeSpan);
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static bool operator ==(TimeSpanMillisecondsWrapper t1, TimeSpanMillisecondsWrapper t2)
    {
      return t2 != null && (t1 != null && t1.TimeSpan == t2.TimeSpan);
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static bool operator !=(TimeSpanMillisecondsWrapper t1, TimeSpanMillisecondsWrapper t2)
    {
      return t2 != null && (t1 != null && t1.TimeSpan != t2.TimeSpan);
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static bool operator <(TimeSpanMillisecondsWrapper t1, TimeSpanMillisecondsWrapper t2)
    {
      return t1.TimeSpan < t2.TimeSpan;
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static bool operator <=(TimeSpanMillisecondsWrapper t1, TimeSpanMillisecondsWrapper t2)
    {
      return t1.TimeSpan <= t2.TimeSpan;
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static bool operator >(TimeSpanMillisecondsWrapper t1, TimeSpanMillisecondsWrapper t2)
    {
      return t1.TimeSpan > t2.TimeSpan;
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static bool operator >=(TimeSpanMillisecondsWrapper t1, TimeSpanMillisecondsWrapper t2)
    {
      return t1.TimeSpan >= t2.TimeSpan;
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public override string ToString()
    {
      return TimeSpan.ToString();
    }
  }
}